use core::ptr::null_mut;

use crate::{
    c::rtx_os::{
        osEventFlagsAttr_t, osEventFlagsClear, osEventFlagsId_t, osEventFlagsNew, osEventFlagsSet, osEventFlagsWait, osFlagsWaitAll, osFlagsWaitAny, osRtxEventFlags_t
    },
    error::{parse_flags_error, Error},
    utils::AlignStore,
};

const CB_SIZE: usize = size_of::<osRtxEventFlags_t>();

pub struct EventFlags {
    cb_mem: AlignStore<CB_SIZE>,
    id: osEventFlagsId_t,
}

impl EventFlags {
    pub const fn default() -> Self {
        Self {
            cb_mem: AlignStore::new(),
            id: null_mut(),
        }
    }

    pub unsafe fn new(&mut self, name: &str) {
        let attr = osEventFlagsAttr_t {
            name: name.as_ptr() as *const i8,
            attr_bits: 0,
            cb_mem: self.cb_mem.raw_ptr(),
            cb_size: CB_SIZE as u32,
        };
        self.id = osEventFlagsNew(&attr);
        assert!(self.id != null_mut(), "event falgs create fail");
    }

    pub fn set_flags(&self, flags: u32) -> Result<(), Error> {
        let ret = unsafe { osEventFlagsSet(self.id, flags) };
        parse_flags_error(ret)
    }

    pub fn clear_flags(&self, flags: u32) -> Result<(), Error> {
        let ret = unsafe { osEventFlagsClear(self.id, flags) };
        parse_flags_error(ret)
    }

    pub fn wait_any_flags(&self, flags: u32, timeout: u32) -> Result<(), Error> {
        let ret = unsafe { osEventFlagsWait(self.id, flags, osFlagsWaitAny, timeout) };
        parse_flags_error(ret)
    }

    pub fn wait_all_flags(&self, flags: u32, timeout: u32) -> Result<(), Error> {
        let ret = unsafe {
            osEventFlagsWait(self.id, flags, osFlagsWaitAll, timeout)
        };
        parse_flags_error(ret)
    }

}
